#include <fstream>
#include <QtGui>
#include "measprog.h"
//#include "aprcfg.h"

MeasProg* MeasProg::instance = NULL;

MeasProg::MeasProg()
{
	qDebug() << "q9020 program_s size " << sizeof(program_s);	
	memset(&program, 0xff, sizeof(program_s));

	memcpy(program.kinds[0].kind, "PROGRAM1", 16);
	memcpy(program.serialno, "SL8630", 9);
//	memcpy(program.devTbl, AprCfg::getDevTable(), sizeof(devtbl_s) * MAX_DEV_ASSIGN); 
	program.kindno = 1;
	program.kinds[0].active = PM_ON;

	ushort code = 0;
	AprCfg::getParamCodeByName("1C2_CCOM" ,PM_DEV_ATTR, code); // TODO:
	program.kinds[0].devicetyp = code;

	ushort index = 0;
	AprCfg::getDevIndexByCode(program.kinds[0].devicetyp, index);
	program.kinds[0].deviceidx = index;

	memcpy(program.devTbl, AprCfg::getDevTable(), sizeof(devtbl_s)*MAX_DEV_ASSIGN);

	
	program.filfreq = PM_50HZ;
	program.active 		= PM_ON;
	program.ngcounton		= PM_ON;
	program.rangemode		= 0;
	program.kindno			= 1;
	program.autoseq		= PM_OFF;
	program.warn_ngcount	= 0;
	program.hdr_logic		= 0;
	program.scan			= PM_OFF;
	program.endtime		= 0.5;
	program.offtime		= 0.4;
	program.dlm_k			= 0;

	program.alias.count			= 0;
	program.alias.list[0].typ		= 1;
	program.alias.list[0].group	= 0;

	program.kinds[0].filter		= PM_ON;
	program.kinds[0].ofstcancel	= PM_ON;
	program.kinds[0].ofcl_vl		= PM_ON;
	program.kinds[0].cooldown		= 0;
	program.kinds[0].cool_v1		= 0;
	program.kinds[0].cool_v2		= 0;

	for(int i = 0; i < MAX_CHANNEL_QTY; ++i){
		program.kinds[0].hue_mtemp[i] = 25.0;
		if(program.kinds[0].filter == PM_ON){
			program.kinds[0].hue_mlums[i] = 450.0;
		}else{
			program.kinds[0].hue_mlums[i] = 680.0;
		}
	}	

	program.ffs 		= PM_OFF;//globalCfg.getFfs() 		? PM_ON : PM_OFF;
	program.cntmode	= PM_ON;//globalCfg.getCntClr() 	? PM_ON : PM_OFF;
	program.dliston	= PM_OFF;//globalCfg.getDList() 		? PM_ON : PM_OFF;
	program.tliston	= PM_OFF;//globalCfg.getTList()		? PM_ON : PM_OFF;
	program.nondisp	= PM_OFF;//globalCfg.getNonDisp()	? PM_ON	: PM_OFF;

	program.mmode = PM_REPEAT;
}



/*
MeasProg& MeasProg::instance()
{
	static MeasProg mp;
	qDebug() << "MeasProg::instance() ===============" << &mp;
	return mp;
}
*/
MeasProg* MeasProg::getInstance()
{
	if(NULL == instance){
		instance = new MeasProg;
	}

	return instance;
}


void MeasProg::saveProgToFile(const QString &path)
{
	std::ofstream out;
	out.open(path.toStdString().c_str(), std::ofstream::out | std::ofstream::trunc);
	if(!out.is_open()){
		return;
	}

//	qDebug() << "saveProgToFile - before file operation: " << program.item_no;
	out.write((const char *)&program, sizeof(program_s));
	out.close();
//	qDebug() << "saveProgToFile - after file operation: " << program.item_no;

	progFilePath = path;

	qDebug() << "measprog ====" << program.kinds[0].devicetyp;
}


void MeasProg::saveProgramToFile()
{
	saveProgToFile(progFilePath);
}

void MeasProg::readProgFromFile(const QString &path)
{
	std::ifstream in;
	in.open(path.toStdString().c_str(), std::ifstream::in);
	if(!in.is_open()){
		return;
	}

	in.read((char *)&program, sizeof(program_s));
	in.close();
	
	progFilePath = path;

//	qDebug() << "measprog ====" << program.kinds[0].devicetyp;
}

bool MeasProg::setItem(ushort			index,
					   const QString 	&name,
 				 	   const QString 	&channel,
				 	   const QString 	&waitTime,
				 	   const QString 	&biasRange,
				 	   const QString 	&biasValue,
				 	   const QString 	&measRange,
				 	   const QString 	&measUpper,
				 	   const QString 	&measLower,
				 	   const QString 	&volLimit,
				 	   const QString 	&filOption,
				 	   const QString 	&limitJudge,
				 	   const QString 	&active,
				 	   const det_u*		det)
{
	if(index < 0 || index > MAX_ITEM_QTY - 1){
		return false;
	}

	item_s *item = &program.kinds[0].item[index];
	
	// 分解item name和suffix
	QString itemName = name.left(name.indexOf('_'));
	char suffix = name.at(name.indexOf('_')+1).toAscii();//right(name.indexOf('_'));

	// name
	ushort itemCode = 0;
	AprCfg::getParamCodeByName(itemName, PM_ITEM_ATTR, itemCode);
	item->code = itemCode;

	// suffix
	item->suffix = suffix;

	// channel
	item->ch = channel.toInt();

	// waittime
	item->waittime = waitTime.toDouble();

	// bias range
	ushort brngCode = 0;
	AprCfg::getParamCodeByName(biasRange, PM_BRANGE_ATTR, brngCode);
	item->brange = brngCode;

	// bias value
	item->bvalue = biasValue.toDouble();

	// meas range
	ushort mrngCode = 0;	
	AprCfg::getParamCodeByName(measRange, PM_MRANGE_ATTR, mrngCode);
	item->mrange = mrngCode;

	// meas upper
	item->mhilimit = measUpper.toDouble();

	// meas lower
	item->mlowlimit = measLower.toDouble();

	// voltage limit
	item->vlimit = volLimit.toDouble();

	// filter option
	ushort filCode = 0;
	AprCfg::getParamCodeByName(filOption, PM_FIL_ATTR, filCode);
	item->filter = filCode;

	// limit judge
	ushort limitCode = 0;
	AprCfg::getParamCodeByName(limitJudge, PM_ONOFF_ATTR, limitCode);
	item->limit = limitCode;
	
	// active
	ushort activeCode = 0;
	AprCfg::getParamCodeByName(active, PM_ONOFF_ATTR, activeCode);
	item->active = activeCode;

	item->ele.normal = 0;//info[4];
	item->ele.reverse = 0;//info[5];
	item->ele.partner = 0;//info[0];
	item->ele.norpol = 0;//info[1];
	item->ele.partner_rev = 0;//info[2];
	item->ele.revpol = 0;//info[3];

	switch(item->code){
	case PM_ESD:
		item->det.esd[0].ino = 0;
		item->det.esd[1].ino = 0;
		break;
	default:
//		item->det.hue.autorange = PM_ON;
//		item->det.hue.ofstcancel = PM_ON;
//		item->det.hue.mrng1 = item->det.hue.mrng2 = item->det.hue.mrng3 = PM_H10_00uA;
//		item->det.hue.scf1 = item->det.hue.scf2 = item->det.hue.scf3 = PM_HX1;
		memcpy(&item->det, det, sizeof(det_u));
		break;
	}


//	memcpy(&program->kinds[0].item[index], item, sizeof(item_s));
//	qDebug() << "MeasProg::setItem ========";
//	qDebug() << program.kinds[0].item[index].brange << "," << program.kinds[0].item[index].bvalue;

	return true;
}

bool MeasProg::getItem(ushort	index,
					   QString 	&name, 
				 	   QString 	&channel, 
				 	   QString 	&waitTime,
				 	   QString 	&biasRange,
				 	   QString 	&biasValue,
				 	   QString 	&measRange,
				 	   QString 	&measUpper,
				 	   QString 	&measLower,
				 	   QString 	&volLimit,
				 	   QString 	&filOption,
				 	   QString 	&limitJudge,
				 	   QString 	&active,
					   det_u*	det)
{
	if(index < 0 || index > MAX_ITEM_QTY - 1){
		return false;
	}

	item_s *item = &program.kinds[0].item[index];

	// name & suffix
	AprCfg::getParamNameByCode(item->code, name);
	name = name + "_" + item->suffix;

	// channel
	channel = QString::number(item->ch);

	// waittime
	waitTime = QString::number(item->waittime);

	// bias range
	AprCfg::getParamNameByCode(item->brange, biasRange);

	// bias value
	biasValue = QString::number(item->bvalue);

	// meas range
	AprCfg::getParamNameByCode(item->mrange, measRange);

	// meas upper
	measUpper = QString::number(item->mhilimit);

	// meas lower
	measLower = QString::number(item->mlowlimit);

	// voltage limit
	volLimit = QString::number(item->vlimit);

	// filter option
	AprCfg::getParamNameByCode(item->filter, filOption);

	// limit judge
	AprCfg::getParamNameByCode(item->limit, limitJudge);

	// active
	AprCfg::getParamNameByCode(item->active, active);
	
	if(PM_ESD == item->code){
	}else{
		memcpy(det, &item->det, sizeof(det_u));
	}

	return true;
}


int MeasProg::getMeasMode()
{
	ushort mcode = 0;
	QString str;
	str = "AUTO";
	AprCfg::getParamCodeByName(str, PM_MMODE_ATTR, mcode);
	if(program.mmode == mcode){
		return 1;
	}

	str = "MANUAL";
	AprCfg::getParamCodeByName(str, PM_MMODE_ATTR, mcode);
	if(program.mmode == mcode){
		return 2;
	}

	str = "REPEAT";
	AprCfg::getParamCodeByName(str, PM_MMODE_ATTR, mcode);
	if(program.mmode == mcode){
		return 3;
	}

	return 1;
}
